
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.SequentialGroup;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.UIManager;

public class WorldMapInterface extends JPanel{
	
	private static final long serialVersionUID = 1L;
	static int width;
	static int height;
	static final int PIXEL_SIZE = 2;
	static final int rows = 27;
	static final int cols = 50;
    GroupLayout layout;
    Random random = new Random();
    Random seed;
	private Component[][] grid = new Component[rows][cols];
	Button lastButton;
	InterfaceFrame interfaceFrame;
	Player player;
	Map map;
	ArrayList<MapNode> nodeList = new ArrayList<MapNode>();
	ArrayList<Edge> edgeList = new ArrayList<Edge>();
	TerrainType[][] terrain = new TerrainType[rows][cols];
	JLabel infoLabel = new JLabel();
	Glass glass=new Glass();
	
	WorldMapInterface( InterfaceFrame interfaceFrame,Player player, Map map){
		this.interfaceFrame=interfaceFrame;
		this.map = map;
		this.player = player;
		nodeList = map.nodes;
		edgeList = map.edges;
		terrain = map.tiles;
		layout = new GroupLayout(this);
		setLayout(layout);
		layout.setAutoCreateContainerGaps(false);
		showMap();
		
		interfaceFrame.setGlassPane(glass);
		glass.setVisible(true);
		//interfaceFrame.getContentPane().repaint();
		width = interfaceFrame.getContentPane().getWidth();
		height = interfaceFrame.getContentPane().getHeight();

		infoLabel.setBounds(width/2-200,height/2-30,400,60);
		infoLabel.setHorizontalAlignment(SwingConstants.CENTER);
		infoLabel.setText("");
		infoLabel.setVisible(false);
		infoLabel.setOpaque(true);
		glass.add(infoLabel);
		infoLabel.addMouseListener(new ButtonListener());
		addKeyBindings();
	}
	
	/**
	 * the worldmap interface. Kommer generara en randomkarta.
	 * @param frame en fin map att ripa på?
	 */
	WorldMapInterface(Map map){
	
		seed = new Random();
		this.map = map;
		nodeList = map.nodes;
		edgeList = map.edges;
		terrain = map.tiles;
		layout = new GroupLayout(this);
		setLayout(layout);
		layout.setAutoCreateContainerGaps(false);
		//showMap();

	}
	 public void showMap(){
         
         for(int i = 0; i < nodeList.size(); i++){
                
                 MapNode node = nodeList.get(i);
                 Button button = new Button(node.x, node.y, node);
                 grid[node.y][node.x] = button;
                 if(i == player.nodeIndex){
                	 lastButton = (Button) grid[node.y][node.x];
                     lastButton.label.setIcon(new ImageIcon(getClass().getResource("/Pics/buttonPressed.gif")));
                     repaint();
                 }
                 else if(map.nodes.get(i).distance == 1){
                	button.label.setIcon(new ImageIcon(getClass().getResource("/Pics/gymButton.gif")));
                 	repaint();
                 }
                 else if(player.defeatedTrainers.contains(i)) {
                	 button.label.setIcon(new ImageIcon(getClass().getResource("/Pics/buttonBeat.gif")));
                	 repaint();
                 }
                 else if(map.adjacent(map.nodes.get(player.nodeIndex), nodeList.get(i))){
                	 button.label.setIcon(new ImageIcon(getClass().getResource("/Pics/buttonUseable.gif")));
                	 repaint();
                 }
                 button.addMouseListener(new ButtonListener());
                
         }
        
         for(int i = 0; i < terrain.length; i++){
                 for(int j = 0; j < terrain[i].length; j++){
                         if(grid[i][j] == null){
                                 if(terrain[i][j].equals(TerrainType.Forest)){
                                         grid[i][j] = new Forest();
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Cabin)){
                                         grid[i][j] = new Cabin();
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Field)){
                                         grid[i][j] = new Field();
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Mountains)){
                                         grid[i][j] = new Mountains();
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Swamp)){
                                     grid[i][j] = new Swamp();
                             }
                                 else if(terrain[i][j].equals(TerrainType.Lake)){
                                         grid[i][j] = new Lake();
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Village)){
                                         grid[i][j] = new Village(TerrainType.Village);
                                 }
                                 else if(terrain[i][j].equals(TerrainType.City)){
                                         grid[i][j] = new City(TerrainType.City);
                                 }
                                 else if(terrain[i][j].equals(TerrainType.Sand)){
                                         grid[i][j] = new Sand();
                                 }
                         }      
                 }
         }
        
         SequentialGroup[] horizontalGroups = new SequentialGroup[rows];
         SequentialGroup[] verticalGroups = new SequentialGroup[cols];
         for(int y = 0; y < rows; y++){  
                 SequentialGroup sGroup = layout.createSequentialGroup();
                 for(int x = 0; x < cols; x++){
                        
                         sGroup.addComponent(grid[y][x]);
                 }
                 horizontalGroups[y] = sGroup;
         }

         for(int x = 0; x < cols; x++){
                 SequentialGroup sGroup = layout.createSequentialGroup();
                
                 for(int y = 0; y < rows; y++){
                        
                         sGroup.addComponent(grid[y][x]);
                 }
                
                 verticalGroups[x] = sGroup;
         }

         layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                 .addGroup(horizontalGroups[0]).addGroup(horizontalGroups[1]).addGroup(horizontalGroups[2]).addGroup(horizontalGroups[3]).addGroup(horizontalGroups[4])
                 .addGroup(horizontalGroups[5]).addGroup(horizontalGroups[6]).addGroup(horizontalGroups[7]).addGroup(horizontalGroups[8]).addGroup(horizontalGroups[9])
                 .addGroup(horizontalGroups[10]).addGroup(horizontalGroups[11]).addGroup(horizontalGroups[12]).addGroup(horizontalGroups[13]).addGroup(horizontalGroups[14])
                 .addGroup(horizontalGroups[15]).addGroup(horizontalGroups[16]).addGroup(horizontalGroups[17]).addGroup(horizontalGroups[18]).addGroup(horizontalGroups[19])
                 .addGroup(horizontalGroups[20]).addGroup(horizontalGroups[21]).addGroup(horizontalGroups[22]).addGroup(horizontalGroups[23]).addGroup(horizontalGroups[24])
                 .addGroup(horizontalGroups[25]).addGroup(horizontalGroups[26])
         );

        
         layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                         .addGroup(verticalGroups[0]).addGroup(verticalGroups[1]).addGroup(verticalGroups[2]).addGroup(verticalGroups[3]).addGroup(verticalGroups[4])
                         .addGroup(verticalGroups[5]).addGroup(verticalGroups[6]).addGroup(verticalGroups[7]).addGroup(verticalGroups[8]).addGroup(verticalGroups[9])
                         .addGroup(verticalGroups[10]).addGroup(verticalGroups[11]).addGroup(verticalGroups[12]).addGroup(verticalGroups[13]).addGroup(verticalGroups[14])
                         .addGroup(verticalGroups[15]).addGroup(verticalGroups[16]).addGroup(verticalGroups[17]).addGroup(verticalGroups[18]).addGroup(verticalGroups[19])
                         .addGroup(verticalGroups[20]).addGroup(verticalGroups[21]).addGroup(verticalGroups[22]).addGroup(verticalGroups[23]).addGroup(verticalGroups[24])
                         .addGroup(verticalGroups[25]).addGroup(verticalGroups[26]).addGroup(verticalGroups[27]).addGroup(verticalGroups[28]).addGroup(verticalGroups[29])
                         .addGroup(verticalGroups[30]).addGroup(verticalGroups[31]).addGroup(verticalGroups[32]).addGroup(verticalGroups[33]).addGroup(verticalGroups[34])
                         .addGroup(verticalGroups[35]).addGroup(verticalGroups[36]).addGroup(verticalGroups[37]).addGroup(verticalGroups[38]).addGroup(verticalGroups[39])
                         .addGroup(verticalGroups[40]).addGroup(verticalGroups[41]).addGroup(verticalGroups[42]).addGroup(verticalGroups[43]).addGroup(verticalGroups[44])
                         .addGroup(verticalGroups[45]).addGroup(verticalGroups[46]).addGroup(verticalGroups[47]).addGroup(verticalGroups[48]).addGroup(verticalGroups[49])
         );
         

	}

	 
	
	public void saveMap(JPanel panel) {

		BufferedImage image=new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
		
		Graphics2D g2=(Graphics2D)image.getGraphics();
			
		panel.paint(g2);
		
		try {
			ImageIO.write(image, "png", new File("karta.png"));
		} catch (Exception e) {
			
		}
	
	}
	private class ButtonListener implements MouseListener{

		@Override
		public void mouseClicked(MouseEvent arg0) {
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			// TODO: Hover image stuff thingey för knappar
			
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			// TODO: Hover image stuff thingey för knappar
			
		}

		@Override
		public void mousePressed(MouseEvent e){
			infoLabel.setVisible(false);
			if (e.getComponent() instanceof Button) {
				Button temp = (Button) e.getComponent();
				Button button = (Button) grid[temp.y][temp.x];
				
				
				for(int i = 0; i < nodeList.size(); i++){
					if(nodeList.get(i).x == button.x && nodeList.get(i).y == button.y){
						if (map.adjacent(map.nodes.get(player.nodeIndex), nodeList.get(i))) {
							int probability = 0;
							switch (nodeList.get(i).type) {
							case Forest:
					        case Sand:
					        case Mountains:
					        	probability = 95;
					        	break;
					        case Cabin:
					        case Field:
					        case Swamp:
					        case Lake:
					        	probability = 75;
					        	break;
					        case Village:
					        	probability = 30;
					        	break;
					        case City:
					        	probability = 10;
					        	break;
							}
					    	if (new Random().nextInt(100) < probability && player.nodeIndex != i) {
					    		interfaceFrame.swapToCombatSkeleton(nodeList.get(i).getRandomEncounter(null), true, map.nodes.get(player.nodeIndex));
					    		UIManager.put("MenuItem.selectionBackground", new Color(163,184,204));
								UIManager.put("MenuItem.selectionForeground", Color.BLACK);
					    	} else {
					    		interfaceFrame.swapToNodeInterface(i, false);
					    	}
							player.nodeIndex = i;
							glass.setVisible(false);
						} else {
							infoLabel.setVisible(true);
							infoLabel.setText("Kan inte gå till en nod som det inte finns väg till!");
						}
					}
				}
			}
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
		}
		
	}
	class Glass extends JComponent{

		// JComponent vill ha för att bli klad.
		private static final long serialVersionUID = 5923332092972390000L;

		protected void paintComponent(Graphics g){
			Graphics2D g2= (Graphics2D) g;
			super.paintComponent(g);
			
			for (Edge e : map.edges) {
				if (e.involves(map.nodes.get(player.nodeIndex))) {
					g2.setColor(Color.WHITE);
				} else {
					g2.setColor(Color.GRAY);
				}
				g2.setStroke(new BasicStroke(5));
				g2.drawLine(e.a.x*24+12, e.a.y*24+12, e.b.x*24+12, e.b.y*24+12);
			}
		}
	}
	
	public void addKeyBindings(){
		
		InputMap im = getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
	    ActionMap am = getActionMap();

	    im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Escape");	

	    am.put("Escape", new KeyAction("Escape"));
	    
	}
	
	private class KeyAction extends AbstractAction{
		

	    private String cmd;

	    KeyAction(String cmd) {
	        this.cmd = cmd;
	    }
		
		private static final long serialVersionUID = 1L;

		@Override
		public void actionPerformed(ActionEvent arg0) {
			
			if(cmd.equals("Escape")){
				interfaceFrame.swapToNodeInterface(player.nodeIndex, false);
				glass.setVisible(false);
			}
			
		}
	}
}

